package db

import (
	"context"
	"fmt"
	"log"
	"sync"

	"gitee.com/daonna/collab-manage-system/ent"

	_ "github.com/go-sql-driver/mysql"
	"gopkg.in/ini.v1"
)

// DBConfig 数据库配置结构体
type DBConfig struct {
	User     string
	Password string
	Host     string
	Port     string
	Database string
	Charset  string
}

var (
	globalDBClient *DBClient
	once           sync.Once
)

// DBClient 数据库客户端封装
type DBClient struct {
	userDB                *ent.Client
	groupDB               *ent.Client
	messageDB             *ent.Client
	conversationDB        *ent.Client
	conversationMemberDB  *ent.Client
	attendanceRecordDB    *ent.Client
	workTimeSettingDB     *ent.Client
	activityDB            *ent.Client
	activityParticipantDB *ent.Client
	activityAttachmentDB  *ent.Client
	departmentDB          *ent.Client
	userDepartmentDB      *ent.Client
	actReviewDB           *ent.Client

	mu sync.RWMutex
}

// VerifyConnections 验证所有数据库连接
func (c *DBClient) VerifyConnections(ctx context.Context) error {
	c.mu.RLock()
	defer c.mu.RUnlock()

	// 验证 user 数据库连接
	if c.userDB != nil {
		if _, err := c.userDB.User.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("user database connection failed: %v", err)
		}
	}

	// 验证 group 数据库连接
	if c.groupDB != nil {
		if _, err := c.groupDB.Conversation.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("group database connection failed: %v", err)
		}
	}

	// 验证 message 数据库连接
	if c.messageDB != nil {
		if _, err := c.messageDB.Message.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("message database connection failed: %v", err)
		}
	}

	// 验证 conversation 数据库连接
	if c.conversationDB != nil {
		if _, err := c.conversationDB.Conversation.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("conversation database connection failed: %v", err)
		}
	}

	// 验证 conversationMember 数据库连接
	if c.conversationMemberDB != nil {
		if _, err := c.conversationMemberDB.ConversationMember.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("conversationMember database connection failed: %v", err)
		}
	}

	// 验证 attendanceRecord 数据库连接
	if c.attendanceRecordDB != nil {
		if _, err := c.attendanceRecordDB.AttendanceRecord.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("attendanceRecord database connection failed: %v", err)
		}
	}

	// 验证 workTimeSetting 数据库连接
	if c.workTimeSettingDB != nil {
		if _, err := c.workTimeSettingDB.WorkTimeSetting.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("workTimeSetting database connection failed: %v", err)
		}
	}

	// 验证 activity 数据库连接
	if c.activityDB != nil {
		if _, err := c.activityDB.Activity.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("activity database connection failed: %v", err)
		}
	}

	// 验证 activityParticipant 数据库连接
	if c.activityParticipantDB != nil {
		if _, err := c.activityParticipantDB.ActivityParticipant.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("activityParticipant database connection failed: %v", err)
		}
	}

	// 验证 activityAttachment 数据库连接
	if c.activityAttachmentDB != nil {
		if _, err := c.activityAttachmentDB.ActivityAttachment.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("activityAttachment database connection failed: %v", err)
		}
	}

	// 验证 department 数据库连接
	if c.departmentDB != nil {
		if _, err := c.departmentDB.Department.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("department database connection failed: %v", err)
		}
	}

	// 验证 userDepartment 数据库连接
	if c.userDepartmentDB != nil {
		if _, err := c.userDepartmentDB.UserDepartment.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("userDepartment database connection failed: %v", err)

		}
	}

	// 验证 actReview 数据库连接
	if c.actReviewDB != nil {
		if _, err := c.actReviewDB.ActReview.Query().
			Select("id").
			Limit(1).
			Count(ctx); err != nil {
			return fmt.Errorf("actReview database connection failed: %v", err)
		}
	}

	return nil
}

// User 获取 user 数据库客户端
func (c *DBClient) User() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.userDB
}

// Group 获取 group 数据库客户端
func (c *DBClient) Group() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.groupDB
}

// Message 获取 message 数据库客户端
func (c *DBClient) Message() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.messageDB
}

// Conversation 获取 conversation 数据库客户端
func (c *DBClient) Conversation() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.conversationDB
}

// ConversationMember 获取 conversationMember 数据库客户端
func (c *DBClient) ConversationMember() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.conversationMemberDB
}

// AttendanceRecord 获取 attendanceRecord 数据库客户端
func (c *DBClient) AttendanceRecord() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.attendanceRecordDB
}

// WorkTimeSetting 获取 workTimeSetting 数据库客户端
func (c *DBClient) WorkTimeSetting() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.workTimeSettingDB
}

// Activity 获取 activity 数据库客户端
func (c *DBClient) Activity() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.activityDB
}

// ActivityParticipant 获取 activityParticipant 数据库客户端
func (c *DBClient) ActivityParticipant() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.activityParticipantDB
}

// ActivityAttachment 获取 activityAttachment 数据库客户端
func (c *DBClient) ActivityAttachment() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.activityAttachmentDB
}

// Department 获取 department 数据库客户端
func (c *DBClient) Department() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.departmentDB
}

// UserDepartment 获取 userDepartment 数据库客户端
func (c *DBClient) UserDepartment() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.userDepartmentDB
}

// ActReview 获取 actReview 数据库客户端
func (c *DBClient) ActReview() *ent.Client {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.actReviewDB
}

// LoadConfig 从配置文件加载数据库配置
func LoadConfig(configPath string) (mysql *DBConfig, err error) {
	file, err := ini.Load(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to load config file: %v", err)
	}

	// 加载 user 配置
	mysql = &DBConfig{
		User:     file.Section("db_user").Key("User").String(),
		Password: file.Section("db_user").Key("Password").String(),
		Host:     file.Section("db_user").Key("Host").String(),
		Port:     file.Section("db_user").Key("Port").String(),
		Database: file.Section("db_user").Key("Database").String(),
		Charset:  file.Section("db_user").Key("Charset").MustString("utf8mb4"),
	}

	return mysql, nil
}

// GetDSN 生成数据库连接字符串
func (c *DBConfig) GetDSN() string {
	return fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local",
		c.User, c.Password, c.Host, c.Port, c.Database, c.Charset)
}

// InitDBClient 初始化数据库客户端
func InitDBClient(mysql *DBConfig) error {
	var err error
	once.Do(func() {
		client := &DBClient{}

		// 连接 user 数据库
		if client.userDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to user: %v", err)
			return
		}

		// 连接 group 数据库
		if client.groupDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to group: %v", err)
			return
		}

		// 连接 message 数据库
		if client.messageDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to message: %v", err)
			return
		}

		// 连接 conversation 数据库
		if client.conversationDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to conversation: %v", err)
			return
		}

		// 连接 conversationMember 数据库
		if client.conversationMemberDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to conversationMember: %v", err)
			return
		}

		// 连接 attendanceRecord 数据库
		if client.attendanceRecordDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to attendanceRecord: %v", err)
			return
		}

		// 连接 workTimeSetting 数据库
		if client.workTimeSettingDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to workTimeSetting: %v", err)
			return
		}

		// 连接 activity 数据库
		if client.activityDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to activity: %v", err)
			return
		}

		// 连接 activityParticipant 数据库
		if client.activityParticipantDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to activityParticipant: %v", err)
			return
		}

		// 连接 activityAttachment 数据库
		if client.activityAttachmentDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to activityAttachment: %v", err)
			return
		}

		// 连接 department 数据库
		if client.departmentDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to department: %v", err)
			return
		}

		// 连接 userDepartment 数据库
		if client.userDepartmentDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to userDepartment: %v", err)
			return
		}

		// 连接 actReview 数据库
		if client.actReviewDB, err = ent.Open("mysql", mysql.GetDSN()); err != nil {
			client.Close()
			err = fmt.Errorf("failed connecting to actReview: %v", err)
			return
		}

		// 验证所有连接
		ctx := context.Background()
		if err = client.VerifyConnections(ctx); err != nil {
			client.Close()
			return
		}

		globalDBClient = client
	})

	return err
}

// GetDBClient 获取全局数据库客户端实例
func GetDBClient() *DBClient {
	return globalDBClient
}

// Close 关闭所有数据库连接
func (c *DBClient) Close() {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.userDB != nil {
		if err := c.userDB.Close(); err != nil {
			log.Printf("Error closing user connection: %v", err)
		}
	}

	if c.groupDB != nil {
		if err := c.groupDB.Close(); err != nil {
			log.Printf("Error closing group connection: %v", err)
		}
	}

	if c.messageDB != nil {
		if err := c.messageDB.Close(); err != nil {
			log.Printf("Error closing message connection: %v", err)
		}
	}

	if c.conversationDB != nil {
		if err := c.conversationDB.Close(); err != nil {
			log.Printf("Error closing conversation connection: %v", err)
		}
	}

	if c.conversationMemberDB != nil {
		if err := c.conversationMemberDB.Close(); err != nil {
			log.Printf("Error closing conversationMember connection: %v", err)
		}
	}

	if c.attendanceRecordDB != nil {
		if err := c.attendanceRecordDB.Close(); err != nil {
			log.Printf("Error closing attendanceRecord connection: %v", err)
		}
	}

	if c.workTimeSettingDB != nil {
		if err := c.workTimeSettingDB.Close(); err != nil {
			log.Printf("Error closing workTimeSetting connection: %v", err)
		}
	}

	if c.activityDB != nil {
		if err := c.activityDB.Close(); err != nil {
			log.Printf("Error closing activity connection: %v", err)
		}
	}

	if c.activityParticipantDB != nil {
		if err := c.activityParticipantDB.Close(); err != nil {
			log.Printf("Error closing activityParticipant connection: %v", err)
		}
	}

	if c.activityAttachmentDB != nil {
		if err := c.activityAttachmentDB.Close(); err != nil {
			log.Printf("Error closing activityAttachment connection: %v", err)
		}
	}

	if c.departmentDB != nil {
		if err := c.departmentDB.Close(); err != nil {
			log.Printf("Error closing department connection: %v", err)
		}
	}

	if c.userDepartmentDB != nil {
		if err := c.userDepartmentDB.Close(); err != nil {
			log.Printf("Error closing userDepartment connection: %v", err)
		}
	}

	if c.actReviewDB != nil {
		if err := c.actReviewDB.Close(); err != nil {
			log.Printf("Error closing actReview connection: %v", err)
		}
	}

}
